Developer Documentation

QuickTime 4 API Documentation

Programming With QuickTime VR

| Previous | Chapter Contents | Chapter Top | Next |

Intercepting QuickTime VR Manager Routines

The QuickTime VR Manager provides support for intercepting some of its routines. To intercept a routine, you need to define and install an intercept procedure, a function that is executed in addition to (or instead of) the QuickTime VR Manager function it's intercepting.

Typically, you'll use an intercept procedure to augment the behavior of a QuickTime VR Manager function. For instance, you might intercept the QTVRSetPanAngle function to play a specific sound when the user moves to a particular pan angle. In this case, you would have the QuickTime VR Manager execute the QTVRSetPanAngle function, and then you would play the appropriate sound.

Alternatively, you might want to override the intercepted function altogether. For instance, you might intercept the QTVRTriggerHotSpot function so that when the user clicks a custom hot spot, you can respond accordingly. In this case, there is no need to have the QuickTime VR Manager execute the QTVRTriggerHotSpot function.

You declare an intercept procedure like this:

pascal void MyInterceptProc (
                     QTVRInstance qtvr,
                     QTVRInterceptPtr qtvrMsg,
                     SInt32 refCon,
                     Boolean *cancel);

The qtvr parameter is the instance with which you're concerned. The qtvrMsg parameter is a pointer to an intercept structure, which contains information about the routine being intercepted and its parameters. The refCon parameter is a long integer available for use by your application. Finally, your intercept procedure should set the cancel parameter to indicate whether the QuickTime VR Manager should execute the intercepted function when your intercept procedure has finished ( false ) or should not execute the function ( true ).

If you don't set the cancel parameter before exiting your intercept procedure, its value is by default set to false (indicating that the intercepted function should be executed).

The intercept structure is defined by the QTVRInterceptRecord data type:

typedef struct QTVRInterceptRecord {
    SInt32                              reserved1;
    SInt32                              selector;
    SInt32                              reserved2;
    SInt32                              reserved3;
    SInt32                              paramCount;
    void                                *parameter[6];
} QTVRInterceptRecord, *QTVRInterceptPtr;

As you can see, many of the fields of an intercept structure are reserved. The interesting fields are selector , paramCount , and parameter . The selector field is an intercept selector, a constant that indicates which routine has triggered your intercept procedure. You can, if you wish, install a single intercept procedure for all intercepted functions. In that case, you can inspect the selector field of the intercept structure passed to your intercept routine to determine how to respond. The QuickTime VR Manager currently defines these intercept selectors:

typedef enum QTVRProcSelector {
    kQTVRSetPanAngleSelector                        = 0x2000,
    kQTVRSetTiltAngleSelector                       = 0x2001,
    kQTVRSetFieldOfViewSelector                     = 0x2002,
    kQTVRSetViewCenterSelector                      = 0x2003,
    kQTVRMouseEnterSelector                         = 0x2004,
    kQTVRMouseWithinSelector                        = 0x2005,
    kQTVRMouseLeaveSelector                         = 0x2006,
    kQTVRMouseDownSelector                          = 0x2007,
    kQTVRMouseStillDownSelector                     = 0x2008,
    kQTVRMouseUpSelector                            = 0x2009,
    kQTVRTriggerHotSpotSelector                     = 0x200A,
    kQTVRGetHotSpotTypeSelector                     = 0x200B
} QTVRProcSelector;

The parameter field of the intercept structure is an array that holds, in order, the parameters that were passed to the intercepted function, minus the QTVR instance parameter. For example, if you intercept the QTVRSetPanAngle function, the parameter array contains a single member, a pointer to a floating-point value that is the new pan angle. You can determine how many members the parameter array contains by inspecting the paramCount field of the intercept structure.

Listing 2-5 defines a simple intercept procedure that is called whenever the QuickTime VR Manager function QTVRSetPanAngle is called. The intercept procedure calls an application-defined function, MyPlayPanSound , to play a sound for the new pan angle.

Listing 5 Intercepting the QTVRSetPanAngle function (version 1)

#define MyPi (3.1415926535898)
#define RadiansToDegrees(x) ((x) * 180.0 / MyPi)

pascal void MyInterceptProc (QTVRInstance theInstance,
                QTVRInterceptPtr theMsg, SInt32 refcon, Boolean *cancel)
{
    Boolean     cancelInterceptedProc = false;
    float       theAngle, *theAnglePtr;
    
    switch (theMsg->selector) {
        case kQTVRSetPanAngleSelector:
            theAnglePtr = theMsg->parameter[0];
            theAngle = *theAnglePtr;
            theAngle = RadiansToDegrees(theAngle);
            MyPlayPanSound(theAngle);       //Play a sound for the angle.
            break;
            
        default:
            break;
    }
    
    *cancel = cancelInterceptedProc;
}

Angular values in the parameter field of an intercept structure are always returned in radians, regardless of the current angular unit. In addition, a floating-point value is always passed as a pointer to a floating-point value.

The intercept procedure defined in Listing 2-5 returns the value false in the cancel parameter. This indicates that the QuickTime VR Manager should call the intercepted function after the intercept procedure exits. If the cancel parameter is set to true , the QuickTime VR Manager does not call the intercepted function. This is useful if you want to replace the intercepted function altogether or if you want to call the intercepted function from within your intercept procedure. For example, if you want to play a sound after the new pan angle is displayed, you can define an intercept procedure like the one in Listing 2-6 .

Listing 6 Intercepting the QTVRSetPanAngle function (version 2)

pascal void MyInterceptProc (QTVRInstance theInstance,
    QTVRInterceptPtr theMsg, SInt32 refcon, Boolean *cancel)
{
    Boolean cancelInterceptedProc = false;

    switch (theMsg->selector) {
        case kQTVRGetHotSpotTypeSelector:
        {
        OSType hsType;
        QTVRCallInterceptedProc (theInstance, theMsg);
        hsType = * ((UInt32 *) theMsg->parameter[1]);
        // Turn all url hotspots into undefined hotspots
        if (hsType == kQTVRHotSpotURLType)
            * ((UInt32 *) theMsg->parameter[1]) = kQTVRHotSpotUndefinedType;
        cancelInterceptedProc = true;
        break;
        }

    default:
        break;
}

*cancel = cancelInterceptedProc;
}

The intercept procedure defined in Listing 2-6 looks at the hot spot type returned by the call to QTVRCallInterceptedProc and changes it to undefined if it is a URL hot spot.

Notice that the new intercept procedure returns the value true in the cancel parameter, indicating that the QuickTime VR Manager should not call the intercepted function after the intercept procedure returns. If the intercept procedure returns false , then the intercepted function will be called twice (once because you call QTVRCallInterceptedProc and a second time because you return false in the cancel parameter).

You should use the QTVRCallInterceptedProc function only in an intercept procedure. Moreover, you should use QTVRCallInterceptedProc instead of the function you're intercepting. If you called QTVRSetPanAngle directly in Listing 2-6 , your intercept procedure would be called repeatedly until your stack overflowed.

You install an intercept procedure by calling the QTVRInstallInterceptProc function, as shown in Listing 2-7 .

Listing 7 Installing an intercept procedure

QTVRInterceptUPP MyInstallInterceptProcedure (QTVRInstance theInstance)
{
    QTVRInterceptUPP    theInterceptProc;

    theInterceptProc = NewQTVRInterceptProc(MyInterceptProc);
    QTVRInstallInterceptProc(theInstance, kQTVRSetPanAngleSelector,
                                                theInterceptProc, 0, 0);
    return  theInterceptProc
}
. . .
myProc = MyInstallInterceptProcedure(qtvr);

QTVRInstallInterceptProc takes an intercept selector to determine which QuickTime VR Manager function to intercept. If you wish, you can define a single intercept procedure and use the intercept selector passed to it in the selector field of theMsg to decide how to respond.

When you no longer need the intercept procedure you should call QTVRInstallInterceptProc again with the same selector and a nil procedure pointer and then call DisposeRoutineDescriptor on myProc .


© 1998 Apple Computer, Inc.

| Previous | Chapter Contents | Chapter Top | Next |